#include "stdafx.h"

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(hwnd, message, wParam, lParam);
	}
}

Window::Window(HINSTANCE hinstance)
{
	SCREEN_X = GetSystemMetrics(SM_CXSCREEN);
	SCREEN_Y = GetSystemMetrics(SM_CYSCREEN);

	hinst = hinstance;
	create_window();

	init_gdip();
	generate_graphics();
}

Window::~Window()
{
}

void Window::create_window()
{
	WNDCLASSEX wc = { 0 };

	wc.hInstance = hinst;
	wc.cbSize = sizeof(WNDCLASSEX);
	wc.hCursor = LoadCursor(hinst, IDC_ARROW);
	wc.hIcon = LoadIcon(hinst, IDI_APPLICATION);
	wc.hIconSm = LoadIcon(hinst, IDI_APPLICATION);
	wc.lpszClassName = L"Window";
	wc.hbrBackground = NULL;
	wc.lpfnWndProc = WndProc;

	if (RegisterClassEx(&wc))
	{
		hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, L"Window", L"Window", WS_OVERLAPPEDWINDOW, 0, 0, 500, 500, NULL, NULL, hinst, NULL);
		if (hwnd)
		{
			ShowWindow(hwnd, 1);
			UpdateWindow(hwnd);
		}
	}
}

void Window::generate_graphics()
{
	hdc = GetDC(hwnd);
	memDC = CreateCompatibleDC(hdc);
	HBITMAP hbmp = CreateCompatibleBitmap(hdc, SCREEN_X, SCREEN_Y);
	SelectObject(memDC, hbmp);
	DeleteObject(hbmp);

	graphics = new Gdiplus::Graphics(memDC);
}

void Window::init_gdip()
{
	Gdiplus::GdiplusStartupInput gsi;
	ULONG_PTR token;

	Gdiplus::GdiplusStartup(&token, &gsi, NULL);
}

int Window::loop()
{
	MSG msg;

	do
	{
		if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
		else
		{
			frame();
		}
	} while (msg.message != WM_QUIT);

	return 0;
}

bool Window::frame()
{
	get_and_dispatch_input();                             //gets and dispatches inputs, such as mouse event and keyboard event
														  //all inputs are process by scenes

	if(curScene)
		curScene->draw(*graphics);

	BitBlt(hdc, 0, 0, SCREEN_X, SCREEN_Y, memDC, 0, 0, SRCCOPY);
	return true;
}

void Window::get_and_dispatch_input()
{
	static BOOL lastKeyState[256] = { FALSE };
	BOOL curKeyState[256];

	static POINT lastmpt = { 0,0 };
	POINT mpt;

	HWND fore = GetForegroundWindow();
	if (fore == hwnd)
	{
		GetCursorPos(&mpt);
		ScreenToClient(hwnd, &mpt);
		if (mpt.x != lastmpt.x || mpt.y != lastmpt.y)
		{
			if (GetAsyncKeyState(VK_LBUTTON) < 0)
			{
				if(curScene)
					curScene->MouseMove(MOUSE_LEFT, mpt.x, mpt.y);
			}
			else if (GetAsyncKeyState(VK_RBUTTON) < 0)
			{
				if(curScene)
					curScene->MouseMove(MOUSE_RIGHT, mpt.x, mpt.y);
			}
			else if (GetAsyncKeyState(VK_MBUTTON) < 0)
			{
				if(curScene)
					curScene->MouseMove(MOUSE_MIDDLE, mpt.x, mpt.y);
			}
			else
			{
				if(curScene)
					curScene->MouseMove(MOUSE_NONE, mpt.x, mpt.y);
			}
		}
		for (int i = 0; i < 256; i++)
		{
			curKeyState[i] = GetAsyncKeyState(i) < 0;
			if (curKeyState[i] && !lastKeyState[i])                               //detect KEYDOWN
			{
				if (i == 0x01)													  //left button down
				{
					if(curScene)
						curScene->LButtonDown(mpt.x, mpt.y);
				}
				else if (i == 0x02)												  //right button u
				{
					if(curScene)
						curScene->LButtonUp(mpt.x, mpt.y);
				}
				else if (i == 0x04)												  //middle button down
				{
				}
				else															  //key down
				{
					if(curScene)
						curScene->KeyDown(i);
				}
			}
			else if (!curKeyState[i] && lastKeyState[i])                          //detetct KEYUP
			{
				if (i == 0x01)													  //left button up
				{
					if(curScene)
						curScene->LButtonUp(mpt.x, mpt.y);
				}
				else if (i == 0x02)												  //right button up
				{
					if(curScene)
						curScene->RButtonUp(mpt.x, mpt.y);
				}
				else if (i == 0x04)												  //middle button up
				{
					MSG(L"MBUTTONUP");
				}
				else															  //key up
				{
					if(curScene)
						curScene->KeyUp(i);
				}
			}

			lastKeyState[i] = curKeyState[i];
			lastmpt = mpt;
		}
	}
}

void Window::bind_scene(Scene * scene)
{
	curScene = scene;
	curScene->graphics = graphics;
}